home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Windows Expert
/
Windows Expert.iso
/
others
/
ole_101.zip
/
PATRON.ZIP
/
PATRON.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-04-13
|
18KB
|
626 lines
/*
* PATRON.C
*
* Basic Windows application code, nothing specific to do with
* OLE except directing various menu commands to function in other
* modules that demonstrate the specific OLE library calls.
*
* Copyright(c) Microsoft Corp. 1992 All Rights Reserved
*
*/
#include <windows.h>
#include <ole.h>
#include <shellapi.h>
#include "oclient.h"
#include "blackbox.h"
#include "patron.h"
/*
* Array of pointers to strings loaded from the resource file.
* Pointers can be near since we'll use LocalAlloc for
* the string space.
*/
char NEAR *rgpsz[CSTRINGS];
//Global variable block.
GLOBALS stGlobals;
LPGLOBALS pGlob=&stGlobals;
//Pointer to OLE information, passed to OLE-specific functions
LPDOCUMENT pDoc;
/*
* WinMain
*
* Purpose:
* Main entry point of application. Should register the app class
* if a previous instance has not done so and do any other one-time
* initializations.
*
* Parameters:
* See Windows SDK Guide to Programming, page 2-3
*
* Return Value:
* Value to return to Windows--termination code.
*
*/
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
HWND hWnd;
MSG msg;
pGlob->hInst=hInstance;
pGlob->pszCmdLine=lpszCmdLine;
if (!FApplicationInit(pGlob, hPrevInstance))
{
FApplicationExit(pGlob);
return FALSE;
}
//Make hWnd available to everyone by placing it in pGlob
hWnd=CreateWindow(rgpsz[IDS_CLASSPATRON], rgpsz[IDS_CAPTION],
WS_MINIMIZEBOX | WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 400, 400,
NULL, NULL, hInstance, NULL);
if (NULL==pGlob->hWnd)
{
FApplicationExit(pGlob);
return FALSE;
}
//Give the window handle and message process functions to the OLE code.
pDoc->hWnd=pGlob->hWnd;
PDocumentMsgProcSet(pDoc, FMessageProcess);
PDocumentBackgroundProcSet(pDoc, NULL);
ShowWindow(pGlob->hWnd, nCmdShow);
UpdateWindow(pGlob->hWnd);
FDirtySet(FALSE);
//Make hAccel available to MessageProcess by placing it in pGlob
pGlob->hAccel=LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATORS));
while (GetMessage(&msg, NULL, 0,0 ))
FMessageProcess(&msg);
FApplicationExit(pGlob);
return msg.wParam;
}
/*
* FMessageProcess
*
* Purpose:
* Simply calls TranslateAccelerator, TranslateMessage, and
* DispatchMessage. We have this in a separate function so
* the FOLEReleaseWait function in OLEOBJ.C can call this separately.
* That way, FOLEReleaseWait does not need to reference pGlob->hWnd
* or pGlob->hAccel like we do here.
*
* Parameters:
* pMsg LPMSG to a message loaded from Get/PeekMessage.
*
* Return Value:
* BOOL TRUE always.
*/
BOOL FAR PASCAL FMessageProcess(LPMSG pMsg)
{
if (!TranslateAccelerator(pGlob->hWnd, pGlob->hAccel, pMsg))
{
TranslateMessage(pMsg);
DispatchMessage(pMsg);
}
return TRUE;
}
/*
* PatronWndProc
*
* Purpose:
* Window class procedure. Standard callback.
*
* Parameters:
* The standard.
*
* Return Value:
* The standard.
*
*/
long FAR PASCAL PatronWndProc(HWND hWnd, UINT iMsg, UINT wParam, LONG lParam)
{
BOOL fOK;
FARPROC lpfn;
WORD wTemp;
RECT rc;
LPOBJECT pObj;
WORD wID[4];
switch (iMsg)
{
case WM_CREATE:
//Set global variable defaults.
pGlob->hWnd=hWnd;
pGlob->hWndLastActive=NULL;
FDirtySet(FALSE);
//Notify Windows that we can take dragged files.
DragAcceptFiles(hWnd, TRUE);
/*
* Load and register any initial document. The TRUE in the
* call to FFileOpen indicates that we're doing this from
* startup and so suppresses the File Open dialog.
*/
if (!FFileOpen(pGlob, pDoc, TRUE))
PostMessage(hWnd, WM_CLOSE, 0, 0L);
break;
case WM_INITMENUPOPUP:
/*
* Check for Save possibility in File menu position 0.
* In and OLE situation, this is always enabled.
*/
if (0==LOWORD(lParam))
{
wTemp=(pGlob->fOpenFile) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED);
EnableMenuItem((HMENU)wParam, IDM_FILESAVE, wTemp | MF_BYCOMMAND);
}
//Check for possibility of Paste for edit menu position 1
if (1==LOWORD(lParam))
{
//Create the OLE Object menu item as necessary.
if (pGlob->hWndLastActive)
pObj=(LPOBJECT)SendMessage(pGlob->hWndLastActive, BBM_POBJECTGET, 0, 0L);
else
pObj=NULL;
MenuOLEVerbAppend((HMENU)wParam, IVERBMENU, IDM_EDITVERBMIN, pDoc, pObj);
/*
* Go enable or disable menu items as necessary. Do OLE menu
* items first, since OLE may disable but the application may still
* want them enabled.
*/
wID[0]=IDM_EDITPASTE;
wID[1]=IDM_EDITPASTELINK;
wID[2]=0;
wID[3]=IDM_EDITLINKS;
MenuOLEClipboardEnable((HMENU)wParam, pDoc, (LPWORD)wID);
MenuClipboardEnable((HMENU)wParam, pGlob);
}
break;
case WM_CLOSE:
if (!FFileExit(pGlob, pDoc))
break;
DestroyWindow(hWnd); //Same as DefWindowProc's action.
break;
case WM_DESTROY:
//Turn off acceptance of dragged files.
DragAcceptFiles(hWnd, FALSE);
PostQuitMessage(0);
break;
case WM_MOVE:
case WM_SIZE:
FDirtySet(TRUE);
break;
case WM_KEYDOWN:
/*
* Activate the current object on an ENTER. Primary verb 0
* is sent in wParam.
*/
if (VK_RETURN==wParam)
SendMessage(pGlob->hWndLastActive, BBM_VERBEXECUTE, 0, 0L);
break;
case WM_DROPFILES:
FCreateFromDropFiles(hWnd, (HANDLE)wParam, pDoc);
break;
case WM_COMMAND:
//Look for an object activation message.
if (wParam >= IDM_EDITVERBMIN && wParam <= IDM_EDITVERBMAX)
{
SendMessage(pGlob->hWndLastActive, BBM_VERBEXECUTE,
wParam-IDM_EDITVERBMIN, 0L);
break;
}
//If a blackbox changes activation, change our variable.
if (wParam >=1000 && BBN_ACTIVATED==HIWORD(lParam))
{
if (NULL!=pGlob->hWndLastActive)
SendMessage(pGlob->hWndLastActive, WM_NCACTIVATE, FALSE, 0L);
pGlob->hWndLastActive=(HWND)LOWORD(lParam);
}
if (wParam >=1000 && (BBN_ACTIVATED!=HIWORD(lParam)))
FDirtySet(TRUE);
switch (wParam)
{
case IDM_FILENEW:
FFileNew(pGlob, pDoc);
break;
case IDM_FILEOPEN:
FFileOpen(pGlob, pDoc, FALSE);
break;
case IDM_FILESAVE:
FFileSave(pGlob, pDoc, FALSE);
break;
case IDM_FILESAVEAS:
fOK=FFileSaveAs(pGlob, pDoc);
return MAKELONG(fOK, 0);
case IDM_FILEEXIT:
PostMessage(hWnd, WM_CLOSE, 0, 0L);
break;
case IDM_EDITCUT:
FEditCut(pGlob);
break;
case IDM_EDITCOPY:
FEditCopy(pGlob, FALSE);
break;
case IDM_EDITPASTE:
case IDM_EDITPASTELINK:
fOK=(IDM_EDITPASTELINK==wParam);
FEditPaste(pGlob, fOK, pDoc);
break;
case IDM_EDITLINKS:
if (FOLELinksEdit(hWnd, pGlob->hInst, pDoc))
FDirtySet(TRUE);
break;
case IDM_EDITINSERTOBJECT:
FEditInsertObject(hWnd, pGlob->hInst, pDoc);
break;
case IDM_EDITCONVERTTOSTATIC:
FEditConvertToStatic(pGlob, pDoc);
break;
case IDM_EDITCLEAR:
//Delete the active window on accelerator or menu command.
if (0==LOWORD(lParam))
WindowDelete(pGlob->hWndLastActive, hWnd);
else
//Delete the provided window.
WindowDelete((HWND)LOWORD(lParam), hWnd);
FDirtySet(TRUE);
break;
case IDM_EDITCLEARALL:
//Release all objects and wait for each to receive OLE_RELEASE.
pDoc->cWait=0;
FObjectsEnumerate(pDoc, FEnumClearAll, 0L);
FOLEReleaseWait(TRUE, pDoc, NULL);
pGlob->hWndLastActive=NULL;
FDirtySet(TRUE);
wTemp=WIDGetNext(TRUE);
PRectGetNext(&rc, TRUE);
break;
case IDM_HELPABOUT:
lpfn=MakeProcInstance(AboutProc, pGlob->hInst);
DialogBox(pGlob->hInst, MAKEINTRESOURCE(IDD_ABOUT),
pGlob->hWnd, lpfn);
FreeProcInstance(lpfn);
break;
}
default:
return (DefWindowProc(hWnd, iMsg, wParam, lParam));
}
return 0L;
}
/*
* FEnumClearAll
*
* Purpose:
* Deletes an object window and calls OleDelete. When OleDelete
* returns OLE_WAIT_FOR_RELEASE, we increment pDoc->cWait so the
* function starting the enumeration can call FOLEReleaseWait once
* for all objects.
*
* Parameters:
* pDoc LPDOCUMENT to the owner of the objects.
* pObj LPOBJECT of the object to delete.
* dw DWORD for extra data, unused.
*
* Return Value:
* BOOL TRUE, indicates to continue enumeration.
*/
BOOL FAR PASCAL FEnumClearAll(LPDOCUMENT pDoc, LPOBJECT pObj, DWORD dw)
{
HWND hWnd;
OLESTATUS os;
//Get the window we stored in this object.
hWnd=(HWND)pObj->hData;
//Delete before destroying the window to insure the data is still around.
os=OleDelete(pObj->pObj);
/*
* We may have already released objects in which case we'll see
* OLE_ERROR_OBJECT.
*/
if (OLE_ERROR_OBJECT!=os)
OsError(os, pDoc, pObj, FALSE);
pObj->hData=NULL;
DestroyWindow(hWnd);
return TRUE;
}
/*
* WindowDelete
*
* Purpose:
* Deletes an object window, including calling OleDelete and activating
* the next window if one exists.
*
* Parameters:
* hWnd HWND to destroy.
* hWndParent HWND of the parent of hWnd.
*
* Return Value:
* None
*/
void FAR PASCAL WindowDelete(HWND hWnd, HWND hWndParent)
{
HWND hWndNext;
HWND hWndPrev;
HWND hWndT;
LPOBJECT pObj;
OLESTATUS os;
/*
* Destroy the given window and activate another, which is either
* the next window in the list from the one being destroyed, the previous
* window, or the first window in the list, if it still exists.
*/
hWndNext=GetWindow(hWnd, GW_HWNDNEXT);
hWndPrev=GetWindow(hWnd, GW_HWNDPREV);
//Logic to determine next window to activate.
hWndT=hWndNext;
if (NULL==hWndT)
hWndT=hWndPrev;
if (NULL==hWndT)
hWndT=GetWindow(hWndParent, GW_CHILD);
pObj=(LPOBJECT)SendMessage(hWnd, BBM_POBJECTGET, 0, 0L);
os=OleDelete(pObj->pObj);
os=OsError(os, pDoc, pObj, TRUE);
if (hWndT==hWnd)
hWndT=NULL;
DestroyWindow(hWnd);
//Activate the new first active window.
pGlob->hWndLastActive=NULL;
if (NULL!=hWndT)
{
BringWindowToTop(hWndT);
SendMessage(hWndT, WM_NCACTIVATE, TRUE, 0L);
}
return;
}
/*
* AboutProc
*
* Purpose:
* Dialog procedure for the omnipresent About box.
*
* Parameters:
* The standard.
*
* Return Value:
* The value to be returned through the DialogBox call that
* created the dialog.
*
*/
BOOL FAR PASCAL AboutProc(HWND hDlg, UINT iMsg, UINT wParam, LONG lParam)
{
switch (iMsg)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
switch (wParam)
{
case IDOK:
EndDialog(hDlg, TRUE);
}
break;
}
return FALSE;
}
/*
* ClientCallback
*
* Purpose:
* OLECLI calls this function for various events in the server
* application:
*
* OLE_CHANGED: The object was changed in the server application.
* The client repaints the object to show the changes.
*
* OLE_CLOSED: (Embedded objects only) The server that was
* editing the embedded object closed.
*
* OLE_QUERY_PAINT: OLECLI is processing a lengthy draw operation on
* an object, so this notification allows the client
* application to stop drawing if desired.
*
* OLE_QUERY_RETRY: An OLE function call in the client returned
* OLE_BUSY. This notification allows the app
* to attempt to retry the operation or terminate it.
*
* OLE_RELEASE: An asynchronous operation has finished and other
* actions can be taken on the single object affected.
*
* OLE_RENAMED: (Linked objects only) Informs the client that a
* linked object was renamed allowing the client to
* update private data structures. All information
* in OLECLI is already updated.
*
* OLE_SAVED: Informs the client that an object was saved
* (linked object) or updated (embedded objects).
* The client should update and repaint the object.
*
* Parameters:
* pObj LPOBJECT to the object structure given as the LPOLECLIENT
* parameter in various OleCreate calls. This has all our
* object information.
* wCode OLE_NOTIFICATION code informing the client of the action
* taken that affects the object.
* pOLEObj LPOLEOBJECT providing a reference to the object's VTBL.
*
* Return Value:
* int The return value is irrelevant except when wCode
* contains OLE_QUERY_PAINT and OLE_QUERY_RETRY, where
* a TRUE means continue the operation and FALSE means
* abort the operation.
*/
int FAR PASCAL ClientCallback(LPOBJECT pObj, OLE_NOTIFICATION wCode,
LPOLEOBJECT pOLEObj)
{
switch (wCode)
{
case OLE_CLOSED: //Server closed for an embedded object.
SetFocus(pGlob->hWnd);
pObj->fOpen=FALSE;
if (pObj->hData)
PostMessage((HWND)pObj->hData, BBM_OBJECTNOTIFY, wCode, (LONG)pObj);
break;
case OLE_SAVED:
case OLE_CHANGED:
case OLE_RENAMED: //Server Save As on a linked object.
if (pObj->hData)
PostMessage((HWND)pObj->hData, BBM_OBJECTNOTIFY, wCode, (LONG)pObj);
break;
case OLE_RELEASE:
/*
* When an asynchronous operation has completed, OLECLI
* will tell us with OLE_RELEASE. We set pObj->fRelease to
* exit the loop if we're waiting for a single object, or
* decrement pObj->pDoc->cWait which might exit the loop waiting
* for all objects.
*/
pObj->fRelease=TRUE;
pObj->pDoc->cWait--;
break;
case OLE_QUERY_RETRY:
//OLECLI asks if we can continue retrying to get the message through.
break;
case OLE_QUERY_PAINT:
//OLECLI asks if we should continue repainting.
return TRUE;
default:
break;
}
return 0;
}